<html>
<head>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<div id="element" name="element_name"></div>
<script>
description('This test checks that all but a handful of dom constructors throw exceptions, and the rest return reasonable objects. It also tests that those constructors have higher precedence than a document element with the same ID or name.');

var element = document.getElementById("element");

// These objects should throw an exception when their constructor is called
// with no arguments. (Some of them may have working constructors that require
// arguments to be valid.)
var objects_exception = [
    'Attr',
    'CharacterData',
    'CDATASection',
    'DocumentType',
    'Element',
    'HTMLDocument',
    'Node',
    'ProcessingInstruction',
    'HTMLAllCollection',
    'HTMLAnchorElement',
    'HTMLAreaElement',
    'HTMLBaseElement',
    'HTMLBodyElement',
    'HTMLBRElement',
    'HTMLButtonElement',
    'HTMLCanvasElement',
    'HTMLDirectoryElement',
    'HTMLDivElement',
    'HTMLDListElement',
    'HTMLEmbedElement',
    'HTMLFieldSetElement',
    'HTMLFontElement',
    'HTMLFormElement',
    'HTMLFrameElement',
    'HTMLFrameSetElement',
    'HTMLHeadingElement',
    'HTMLHeadElement',
    'HTMLHRElement',
    'HTMLHtmlElement',
    'HTMLIFrameElement',
    'HTMLImageElement',
    'HTMLInputElement',
    'HTMLLabelElement',
    'HTMLLegendElement',
    'HTMLLIElement',
    'HTMLLinkElement',
    'HTMLMapElement',
    'HTMLMarqueeElement',
    'HTMLMenuElement',
    'HTMLMetaElement',
    'HTMLModElement',
    'HTMLObjectElement',
    'HTMLOListElement',
    'HTMLOptGroupElement',
    'HTMLOptionElement',
    'HTMLParagraphElement',
    'HTMLParamElement',
    'HTMLPreElement',
    'HTMLQuoteElement',
    'HTMLScriptElement',
    'HTMLSelectElement',
    'HTMLStyleElement',
    'HTMLTableCaptionElement',
    'HTMLTableColElement',
    'HTMLTableElement',
    'HTMLTableSectionElement',
    'HTMLTableCellElement',
    'HTMLTableRowElement',
    'HTMLTextAreaElement',
    'HTMLTitleElement',
    'HTMLUListElement',
    'HTMLElement',
    'CanvasRenderingContext2D',
    'CSSFontFaceRule',
    'CSSImportRule',
    'CSSMediaRule',
    'CSSPageRule',
    'CSSRule',
    'CSSRuleList',
    'CSSStyleDeclaration',
    'CSSStyleRule',
    'DOMImplementation',
    'HTMLCollection',
    'MediaList',
    'MimeType',
    'MimeTypeArray',
    'MutationEvent',
    'NamedNodeMap',
    'NodeFilter',
    'NodeList',
    'Plugin',
    'PluginArray',
    'StyleSheet',
    'StyleSheetList',
    'TextEvent',
    'XPathResult',
    'BarProp',
    'CanvasGradient',
    'CanvasPattern',
    'Selection',
    'Window',
    'History',
    'HTMLOptionsCollection',
    'Location',
    'Navigator',
    'NodeIterator',
    'Screen',
    'TreeWalker',
    'XPathExpression',
    'Worker'
];

// These objects should have a working constructor.
var objects_constructor = [
    'Comment',
    'CSSStyleSheet',
    'DataTransfer',
    'DOMParser',
    'Document',
    'DocumentFragment',
    'Range',
    'Text',
    'XMLHttpRequest',
    'XMLSerializer',
    'XPathEvaluator',
    'XSLTProcessor'
];

// These objects should have no constructor.
var objects_no_constructor = [
    'EventTargetNode',
    'UndetectableHTMLCollection',
    'XPathNSResolver',
    'EventListener',
    'NPObject'
];

// These objects should have a working constructor, but their constructed
// object names differ. This is therefore a map from constructor name to
// constructed object.
var objects_different_constructor = {
    'Audio': 'HTMLAudioElement',
    'Option': 'HTMLOptionElement',
    'Image': 'HTMLImageElement'
}

function TryAllocate(node) {
    var Cons = this[node];
    if (!Cons) return 'no constructor';
    try { return Object.prototype.toString.call(new Cons()); }
    catch (e) { return 'exception'; }
}

function check(name, expected) {
    actual = TryAllocate(node);
    if (actual == expected) {
      document.write("PASS: " + name + " '" + expected + "'<br>");
    } else {
      document.write("FAIL: " + name + " wanted '" + expected + "', got '" +
          actual + "'<br>");
    }
}

for (var i = 0; i < objects_exception.length; i++) {
    var obj = objects_exception[i];
    shouldBe("TryAllocate('" + obj + "')", "'exception'");
}

for (var i = 0; i < objects_no_constructor.length; i++) {
    var obj = objects_no_constructor[i];
    shouldBe("TryAllocate('" + obj + "')", "'no constructor'");
}

for (var i = 0; i < objects_constructor.length; i++) {
    var obj = objects_constructor[i];
    shouldBe("TryAllocate('" + obj + "')", "'[object " + obj + "]'");
    element.id = obj;
    shouldBe("TryAllocate('" + obj + "')", "'[object " + obj + "]'");
    element.id = "element";
    element.name = obj;
    shouldBe("TryAllocate('" + obj + "')", "'[object " + obj + "]'");
    element.name = "element_name";
}

for (var obj in objects_different_constructor) {
    shouldBe("TryAllocate('" + obj + "')",
             "'[object " + objects_different_constructor[obj] + "]'");
    element.id = obj;
    shouldBe("TryAllocate('" + obj + "')",
             "'[object " + objects_different_constructor[obj] + "]'");
    element.id = "element";
    element.name = obj;
    shouldBe("TryAllocate('" + obj + "')",
             "'[object " + objects_different_constructor[obj] + "]'");
    element.name = "element_name";
}
</script>
</body>
</html>
